package store.lunangangster.nodeflow.parser.helper;

import static store.lunangangster.nodeflow.enums.FlowType.FLOW_THEN;

import java.util.List;
import java.util.function.Function;
import org.dom4j.Document;
import org.dom4j.Element;
import store.lunangangster.nodeflow.builder.NodeBuilder;
import store.lunangangster.nodeflow.builder.entity.ChainProp;
import store.lunangangster.nodeflow.builder.entity.NodeProp;
import store.lunangangster.nodeflow.core.component.NodeComponent;
import store.lunangangster.nodeflow.enums.NodeType;
import store.lunangangster.nodeflow.exception.RuleSourceParseException;
import store.lunangangster.nodeflow.rt.element.flow.Flow;

/**
 * 聚合XML、JSON、YML文件的解析器工具类
 *
 * @author cwk
 * @version 1.0
 */
public class ParserHelper {

	private ParserHelper() {}


	/**
	 * 根据NodeProp来创建Node对象，并且加载到FlowBus中
	 */
	public static void buildNode(NodeProp nodeProp) throws RuleSourceParseException {
		if (nodeProp == null) {
			return;
		}
		String nodeId = nodeProp.getId();
		String className = nodeProp.getClassName();
		Class<?> clazz;
		NodeType nodeType;
		NodeComponent nodeComp;
		try {
			// 获取原class
			clazz = Class.forName(className);
			// 猜测其NodeType
			nodeType = NodeType.guessType(clazz);
			if (nodeType == null) {
				throw new RuleSourceParseException("Find no correct nodeType for className: " + className);
			}
			// 获取其对应的NodeComponent
			nodeComp = (NodeComponent) clazz.newInstance();
		} catch (ClassNotFoundException e) {
			throw new RuleSourceParseException("Find no correct class for className: " + className, e);
		} catch (InstantiationException | IllegalAccessException e) {
			throw new RuleSourceParseException("Class cannot be instantiated: " + className, e);
		}
		NodeBuilder.start()
				.id(nodeId)
				.className(className)
				.clazz(clazz)
				.type(nodeType)
				.component(nodeComp)
				.build();
	}

	/**
	 * 相邻ThenFlow的合并逻辑，将<code>latter</code>与<code>former</code>进行合并
	 * @param former   待合并flow
	 * @param latter   被合并flow
	 * @return  如果可以合并则返回true
	 */
	public static boolean mergeFlow(Flow former, Flow latter) {
		if (former == null) {
			return false;
		}
		if (latter == null) {
			return true;
		}
		// 只有相邻的Then才可以合并
		if (!FLOW_THEN.equals(former.getFlowType()) || !FLOW_THEN.equals(latter.getFlowType())) {
			return false;
		}
		former.getExecutableList().addAll(latter.getExecutableList());
		return true;
	}

	// XML解析Nodes方法
	public static void parseNodes(List<Document> documents) throws RuleSourceParseException {
		XmlParserHelper.parseNodes(documents);
	}

	// XML解析Chains方法
	public static void parseChains(List<Document> documents, Function<Element, ChainProp> chainParser)
			throws RuleSourceParseException {
		XmlParserHelper.parseChains(documents, chainParser);
	}
}
